home *** CD-ROM | disk | FTP | other *** search
- #include <ToolUtils.h>
- #include <Memory.h>
- #include <QuickDraw.h>
- #include <FixMath.h>
-
- #include "curves.h"
-
- int OnCurve(long* bits, long index)
- {
- bits += index >> 5;
- index &= 31;
- return (*bits & (0x80000000 >> index)) == 0;
- }
-
- void FrameCurve(curve* cur, int level)
- {
- if (level)
- { curve left, right;
-
- left.start = cur->start;
- left.control.x = AVE(cur->start.x, cur->control.x);
- left.control.y = AVE(cur->start.y, cur->control.y);
- right.control.x = AVE(cur->control.x, cur->end.x);
- right.control.y = AVE(cur->control.y, cur->end.y);
- left.end.x = right.start.x = AVE(left.control.x, right.control.x);
- left.end.y = right.start.y = AVE(left.control.y, right.control.y);
- right.end = cur->end;
-
- FrameCurve( &left, level-1 );
- FrameCurve( &right, level-1 );
- }
- else
- flineto( cur->end.x, cur->end.y );
- }
-
- path* NextPath(path* aPath)
- {
- return (path*)((long*)aPath + 1 + (aPath->vectors + 31 >> 5) + aPath->vectors * 2);
- }
-
- void InitPathWalker( pathWalker* w, path* aPath )
- {
- w->index = 0;
- w->ep = aPath->vectors - 1;
- w->bits = aPath->controlBits;
- /*
- * skip past the control bits to point to the first point
- */
- w->p = (point*)(w->bits + (aPath->vectors + 31 >> 5));
- }
-
- int NextPathSegment( pathWalker* w)
- {
- long prevIndex, nextIndex;
-
- /* 0 means this is the first segment */
- if (w->index == 0)
- { if (OnCurve(w->bits, w->ep))
- w->c.start = w->p[w->ep];
- else
- { if (OnCurve(w->bits,0))
- { w->c.start = w->p[0];
- w->index = 1;
- }
- else /* start at an implied on-curve point */
- { w->c.start.x = AVE(w->p[0].x, w->p[w->ep].x);
- w->c.start.y = AVE(w->p[0].y, w->p[w->ep].y);
- }
- }
- }
- else /* start where we previously left off */
- w->c.start = w->c.end;
-
- NEXT_SEGMENT:
- /*
- * compute the point index before and after the current one.
- * This wraps around, since we assume the contour is closed.
- */
- prevIndex = w->index == 0 ? w->ep : w->index - 1;
- nextIndex = w->index == w->ep ? 0 : w->index + 1;
-
- if (OnCurve(w->bits, w->index))
- { if (OnCurve(w->bits, prevIndex))
- { w->isLine = true; /* this means we have a line */
- w->c.end = w->p[w->index];
- }
- else if (w->index++ <= w->ep)
- goto NEXT_SEGMENT;
- }
- else
- { w->isLine = false; /* this means we have a curve */
- w->c.control = w->p[w->index];
- if (OnCurve(w->bits, nextIndex))
- w->c.end = w->p[nextIndex];
- else
- { w->c.end.x = AVE(w->p[w->index].x, w->p[nextIndex].x);
- w->c.end.y = AVE(w->p[w->index].y, w->p[nextIndex].y);
- }
- }
-
- return w->index++ <= w->ep; /* return true if there are still more segments */
- }
-
- path* FramePath(path* cont, int closed)
- {
- pathWalker walker;
-
- InitPathWalker(&walker, cont);
- /*
- * The first segment is special, since it calls fmoveto.
- */
- if (NextPathSegment(&walker))
- { fmoveto( walker.c.start.x, walker.c.start.y );
- if (walker.isLine)
- flineto(walker.c.end.x, walker.c.end.y );
- else
- FrameCurve(&walker.c, kCurveLimit);
- }
- /*
- * Keep looping until we run out of segments
- */
- while (NextPathSegment(&walker))
- if (walker.isLine)
- flineto(walker.c.end.x, walker.c.end.y );
- else
- FrameCurve(&walker.c, kCurveLimit);
-
- /*
- * Return the next path, used if this path is one of several within a paths.
- */
- return NextPath(cont);
- }
-
- void FramePaths(paths* aPath, int closed)
- {
- long ctr = aPath->contours;
- path* cont = aPath->contour;
-
- while (ctr--)
- cont = FramePath( cont, closed );
- }
-
- void PaintDiamond(Rect* r)
- {
- short size = sizeof(short) + sizeof(Rect) + sizeof(Point) * 4;
- PolyHandle p = (PolyHandle)NewHandle( size );
- short* pt;
-
- p = OpenPoly();
- MoveTo( r->right + r->left >> 1, r->top - 1 );
- LineTo( r->right , r->top + r->bottom >> 1 );
- LineTo( r->right + r->left >> 1, r->bottom );
- LineTo( r->left - 1, r->top + r->bottom >> 1 );
- ClosePoly();
- PaintPoly(p);
- KillPoly(p);
- }
-
- void ExamplePaths()
- {
- long myPaths[] = {
- 5, /* 5 contours */
- 3, 0xE0000000, 0, ff(16), 0, ff(8), ff(14), ff(12),
- 3, 0xE0000000, ff(8), 0, ff(16), 0, ff(12), ff(14),
- 3, 0xE0000000, ff(24), ff(8), ff(24), ff(16), ff(10), ff(12),
- 3, 0xE0000000, ff(16), ff(24), ff(8), ff(24), ff(12), ff(10),
- 16, 0x11110000,
- ff(8), 0, ff(12), ff(4), ff(16), 0, ff(16), ff(8),
- ff(24), ff(8), ff(20), ff(12), ff(24), ff(16), ff(16), ff(16),
- ff(16), ff(24), ff(12), ff(20), ff(8), ff(24), ff(8), ff(16),
- 0, ff(16), ff(4), ff(12), 0, ff(8), ff(8), ff(8)
- };
-
- ScalePaths((paths*)myPaths, ff(15), ff(15));
- OffsetPaths((paths*)myPaths, ff(25), ff(25));
- FramePaths((paths*)myPaths, 0);
- }
-
- void MarkPaths(paths* aPath)
- {
- long ctr = aPath->contours;
- path* cont = aPath->contour;
- Point loc;
- Rect r;
-
- while (ctr--)
- { long* bits = cont->controlBits;
- long* coord = (long*)(bits + (cont->vectors + 31 >> 5));
- long ptIndex;
-
- for (ptIndex = 0; ptIndex < cont->vectors; ptIndex++)
- { r.left = FR(*coord++) - 2;
- r.top = FR(*coord++) - 2;
- r.right = r.left + 5;
- r.bottom = r.top + 5;
- if (OnCurve(bits, ptIndex))
- PaintOval(&r);
- #if 1
- else
- FillOval(&r, qd.gray);
- #endif
- }
- cont = (path*)coord;
- }
- }
-
- /*
- * Create a new path = dst + src, and then dispose dst.
- */
- paths* AppendPaths(paths* dst, paths* src)
- {
- long dstSize, srcSize = GetPtrSize((Ptr)src);
- paths* newDst;
-
- if (dst)
- { dstSize = GetPtrSize((Ptr)dst);
- newDst = (paths*)NewPtr(dstSize + srcSize - 4);
- }
- else
- newDst = (paths*)NewPtr(srcSize);
-
- if (!newDst || MemError())
- Debugger();
-
- if (dst)
- { BlockMove((Ptr)dst, (Ptr)newDst, dstSize);
- BlockMove((Ptr)src + 4, (Ptr)newDst + dstSize, srcSize - 4);
- *(long*)newDst += *(long*)src;
- DisposePaths(dst);
- }
- else
- BlockMove((Ptr)src, (Ptr)newDst, srcSize);
-
- return newDst;
- }
-
- void DisposePaths(paths* p)
- {
- DisposPtr((Ptr)p);
- }
-
- void GetPathsBounds(paths* p, Rect* r)
- {
- long ctr = p->contours;
- path* cont = p->contour;
-
- r->left = r->top = 32767;
- r->right = r->bottom = -32678;
-
- while (ctr--)
- { long* bits = cont->controlBits;
- long* coord = (long*)(bits + (cont->vectors + 31 >> 5));
- long ptIndex;
-
- for (ptIndex = 0; ptIndex < cont->vectors; ptIndex++)
- { short x = FR(*coord++);
- short y = FR(*coord++);
-
- if (x < r->left) r->left = x; else
- if (x > r->right) r->right = x;
- if (y < r->top) r->top = y; else
- if (y > r->bottom) r->bottom = y;
- }
- cont = (path*)coord;
- }
- }
-
- void OffsetPaths( paths* p, Fixed dx, Fixed dy )
- {
- long ctrs = p->contours;
- path* aPath = p->contour;
-
- while (ctrs--)
- { long pts = aPath->vectors;
- Fixed* coord = (Fixed*)aPath + 1 + (pts + 31 >> 5);
-
- while (pts--)
- { *coord++ += dx;
- *coord++ += dy;
- }
- aPath = (path*)coord;
- }
- }
-
- void ScalePaths(paths* p, Fixed sx, Fixed sy)
- {
- long ctrs = p->contours;
- path* aPath = p->contour;
-
- while (ctrs--)
- { long pts = aPath->vectors;
- Fixed* coord = (Fixed*)aPath + 1 + (pts + 31 >> 5);
-
- while (pts--)
- { *coord = FixMul(*coord, sx);
- coord++;
- *coord = FixMul(*coord, sy);
- coord++;
- }
- aPath = (path*)coord;
- }
- }
-
- void MapPaths(paths* p, Rect* src, Rect* dst)
- {
- Fixed sx = FixDiv( dst->right - dst->left, src->right - src->left );
- Fixed sy = FixDiv( dst->bottom - dst->top, src->bottom - src->top );
-
- OffsetPaths(p, -ff(src->left), -ff(src->top));
- ScalePaths(p, sx, sy);
- OffsetPaths(p, ff(dst->left), ff(dst->top));
- }
-
- long SizeOfPaths(paths* p)
- {
- long size = sizeof(long);
- long ctrs = p->contours;
- path* cont = p->contour;
-
- while (ctrs--)
- { long pathSize = (1 + (cont->vectors + 31 >> 5) + (cont->vectors << 1)) << 2;
-
- size += pathSize;
- cont = (path*)((Ptr)cont + pathSize);
- }
- return size;
- }
-
- paths* CopyPaths(paths* p)
- {
- long size = SizeOfPaths(p);
- Ptr p2 = NewPtr( size );
-
- BlockMove( (Ptr)p, p2, size );
- return (paths*)p2;
- }
-
-